package com.kclm.xsap.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kclm.xsap.entity.*;
import com.kclm.xsap.service.*;
import com.kclm.xsap.utils.R;
import com.kclm.xsap.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Controller
@RequestMapping("/schedule")
public class ScheduleRecordController {
    @Autowired
    private MemberService memberService;
    @Autowired
    private ScheduleRecordService scheduleRecordService;
    @Autowired
    private CourseService courseService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private CourseCardService courseCardService;
    @Autowired
    private MemberBindRecordService memberBindRecordService;
    @Autowired
    private ReservationRecordService reservationRecordService;
    @Autowired
    private ClassRecordService classRecordService;
    @Autowired
    private MemberCardService memberCardService;

    @GetMapping("/x_course_schedule.do")
    public String courseSchedule() {
        return "course/x_course_schedule";
    }

    @GetMapping("/toSearch.do")
    @ResponseBody
    public R toSearch(Long id) {
        System.out.println(id);
        List<ClassRecordEntity> classRecordEntities = classRecordService.list(new QueryWrapper<ClassRecordEntity>()
                .eq("member_id", id)
                .eq("check_status", 0));
        List<ScheduleForConsumeSearchVo> scheduleForConsumeSearchVoList = new ArrayList<>();
        for (ClassRecordEntity classRecordEntity : classRecordEntities) {
            ScheduleForConsumeSearchVo scheduleForConsumeSearchVo = new ScheduleForConsumeSearchVo();
            String name = scheduleRecordService.getresName(classRecordEntity.getScheduleId());
            ScheduleRecordEntity recordServiceById = scheduleRecordService.getById(classRecordEntity.getScheduleId());
            LocalDateTime startTime = LocalDateTime.of(recordServiceById.getStartDate(), recordServiceById.getClassTime());
            scheduleForConsumeSearchVo.setScheduleId(classRecordEntity.getScheduleId());
            scheduleForConsumeSearchVo.setCourseName(name);
            scheduleForConsumeSearchVo.setTeacherName(scheduleRecordService.getresName(classRecordEntity.getScheduleId()));
            scheduleForConsumeSearchVo.setClassDateTime(startTime);
            scheduleForConsumeSearchVoList.add(scheduleForConsumeSearchVo);
        }
        return R.ok().put("value", scheduleForConsumeSearchVoList);
    }

    @PostMapping("/getOneCourse.do")
    @ResponseBody
    public R getOneCourse(@RequestParam("id") Long id, @RequestParam("memberId") Long memberId) {
        System.out.println(id);
        ReservationRecordEntity reservationRecordEntity = reservationRecordService.getOne(new QueryWrapper<ReservationRecordEntity>()
                .eq("schedule_id", id)
                .eq("member_id", memberId));
        ScheduleRecordEntity scheduleRecordEntity = scheduleRecordService.getOne(new QueryWrapper<ScheduleRecordEntity>().eq("id", id));
        CourseEntity courseEntity = courseService.getById(scheduleRecordEntity.getCourseId());
        ScheduleSearchLimitVo scheduleSearchLimitVo = new ScheduleSearchLimitVo();
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(courseEntity.getMoney()));
        BigDecimal result = bigDecimal.multiply(new BigDecimal(reservationRecordEntity.getReserveNums()));
        scheduleSearchLimitVo.setCardCountChange(courseEntity.getTimesCost() * reservationRecordEntity.getReserveNums())
                .setAmountOfConsumption(result);

        return R.ok().put("data", scheduleSearchLimitVo);
    }

    @PostMapping("/scheduleList.do")
    @ResponseBody
    @Cacheable(value = "courseCache", key = "1")
    public List<CourseScheduleVo> scheduleList() {
        List<ScheduleRecordEntity> scheduleRecordEntityList = scheduleRecordService.list(null);
        List<CourseScheduleVo> courseScheduleVoList = new ArrayList<>();
        for (ScheduleRecordEntity scheduleRecordEntity : scheduleRecordEntityList) {
            EmployeeEntity employeeById = employeeService.getById(scheduleRecordEntity.getTeacherId());
            if (employeeById != null) {
                CourseEntity courseById = courseService.getById(scheduleRecordEntity.getCourseId());
                LocalDateTime startTime = LocalDateTime.of(scheduleRecordEntity.getStartDate(), scheduleRecordEntity.getClassTime());
                CourseScheduleVo courseScheduleVo = new CourseScheduleVo();
                courseScheduleVo.setColor(courseById.getColor());
                courseScheduleVo.setTitle(courseById.getName() + "【" + employeeById.getName() + "】");
                courseScheduleVo.setStart(startTime);
                courseScheduleVo.setEnd(startTime.plusMinutes(courseById.getDuration()));
                courseScheduleVo.setUrl("x_course_schedule_detail.do?id=" + scheduleRecordEntity.getId());
                courseScheduleVoList.add(courseScheduleVo);
            }
        }
        return courseScheduleVoList;
    }

    @GetMapping("/refreshCache.do")
    @ResponseBody
    @CacheEvict(cacheNames = "courseCache", key = "1")
    public R refreshCache() {
        return R.ok();
    }

    @GetMapping("/x_course_schedule_detail.do")
    public String courseScheduleDetail(Integer id, Model model) {
        model.addAttribute("ID", id);
        return "course/x_course_schedule_detail";
    }

    @PostMapping("/scheduleDetail.do")
    @ResponseBody
    public R scheduleDetail(Long id) {
        ScheduleDetailsVo scheduleDetailsVo = new ScheduleDetailsVo();
        ScheduleRecordEntity scheduleRecordEntity = scheduleRecordService.getById(id);
        CourseEntity courseEntity = courseService.getById(scheduleRecordEntity.getCourseId());
        LocalDateTime startTime = LocalDateTime.of(scheduleRecordEntity.getStartDate(), scheduleRecordEntity.getClassTime());
        //获取支持的会员卡
        List<String> supportCards = scheduleRecordService.selectCards(id);
        List<String> newSupportCards = new ArrayList<>();
        for (String supportCard : supportCards) {
            newSupportCards.add("「" + supportCard + "」");
        }
        EmployeeEntity employeeEntity = employeeService.getById(scheduleRecordEntity.getTeacherId());
        scheduleDetailsVo.setCourseName(courseEntity.getName())
                .setStartTime(startTime)
                .setEndTime(startTime.plusMinutes(courseEntity.getDuration()))
                .setDuration(courseEntity.getDuration())
                .setLimitAge(courseEntity.getLimitAge())
                .setLimitSex(courseEntity.getLimitSex())
                .setSupportCards(newSupportCards)
                .setTeacherName(employeeEntity.getName())
                .setOrderNums(scheduleRecordEntity.getOrderNums())
                .setClassNumbers(courseEntity.getContains())
                .setTimesCost(courseEntity.getTimesCost());
        return R.ok().put("data", scheduleDetailsVo);
    }

    @PostMapping("/scheduleAdd.do")
    @ResponseBody
    @CacheEvict(value = "courseCache", key = "1")
    public R scheduleAdd(@Valid ScheduleRecordEntity scheduleRecordEntity, BindingResult bindingResult) {

        log.info("Controller==>scheduleRecordEntity==>{}" + scheduleRecordEntity);
        log.info("bindingResult==>{}" + bindingResult);


        if (bindingResult.hasErrors()) {
            HashMap<String, String> errorMap = new HashMap<>();
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
            return R.error(400, "非法参数").put("errorMap", errorMap);
        }


        //判断是否可以排课
        boolean saveOrNot = scheduleRecordService.saveOrNot(scheduleRecordEntity);

        if (saveOrNot) {
            if (scheduleRecordService.save(scheduleRecordEntity)) {
                return R.ok();
            } else {
                return R.error();
            }
        } else {
            return R.error("请在别的时间段内排课!");
        }
    }

    @PostMapping("/scheduleCopy.do")
    @ResponseBody
    @CacheEvict(value = "courseCache", key = "1")
    public R scheduleCopy(@RequestParam("sourceDateStr") String sourceDateStr, @RequestParam("targetDateStr") String targetDateStr) {
        //获取要复制那天的课程数据
        List<ScheduleRecordEntity> scheduleRecordEntityList = scheduleRecordService.list(
                new QueryWrapper<ScheduleRecordEntity>().eq("start_date", sourceDateStr));
        //迭代初始化数据
        for (ScheduleRecordEntity scheduleRecordEntity : scheduleRecordEntityList) {
            scheduleRecordEntity.setStartDate(LocalDate.parse(targetDateStr))
                    .setId(null)
                    .setVersion(1)
                    .setOrderNums(0);
        }
        //判断是否可以复制数据
        boolean isCopy = scheduleRecordService.isCopy(sourceDateStr, targetDateStr, scheduleRecordEntityList);
        if (isCopy) {
            if (scheduleRecordService.saveBatch(scheduleRecordEntityList)) {
                return R.ok();
            } else {
                return R.error();
            }
        } else {
            return R.error("此时间有相同老师的课程，请选择其他时间");
        }
    }

    @PostMapping("/reservedList.do")
    @ResponseBody
    public R reservedList(Long id) {
        boolean flag = true;
        List<ScheduleDetailReservedVo> scheduleDetailReservedVoList = returnList(id, flag);
        return R.ok().put("data", scheduleDetailReservedVoList);
    }

    @PostMapping("/reserveRecord.do")
    @ResponseBody
    public R reserveRecord(Long id) {
        boolean flag = false;
        List<ScheduleDetailReservedVo> scheduleDetailReservedVoList = returnList(id, flag);
        return R.ok().put("data", scheduleDetailReservedVoList);
    }

    private List<ScheduleDetailReservedVo> returnList(Long id, boolean flag) {
        List<ScheduleDetailReservedVo> scheduleDetailReservedVoList = new ArrayList<>();
        ScheduleRecordEntity scheduleRecordServiceById = scheduleRecordService.getById(id);
        CourseEntity courseServiceById = courseService.getById(scheduleRecordServiceById.getCourseId());
        List<ClassRecordEntity> classRecordEntityList;
        if (flag) {
            classRecordEntityList = classRecordService.list(new QueryWrapper<ClassRecordEntity>()
                    .eq("schedule_id", id)
                    .eq("reserve_check", 0));
        } else {
            classRecordEntityList = classRecordService.list(new QueryWrapper<ClassRecordEntity>()
                    .eq("schedule_id", id));
        }
        for (ClassRecordEntity classRecordEntity : classRecordEntityList) {
            ReservationRecordEntity reservationRecordEntity = reservationRecordService.getOne(new QueryWrapper<ReservationRecordEntity>()
                    .eq("member_id", classRecordEntity.getMemberId())
                    .eq("schedule_id", classRecordEntity.getScheduleId())
                    .eq("card_id", classRecordEntity.getBindCardId()));
            MemberEntity memberEntity = memberService.getById(reservationRecordEntity.getMemberId());
            ScheduleDetailReservedVo scheduleDetailReservedVo = new ScheduleDetailReservedVo();
            scheduleDetailReservedVo.setReserveStatus(classRecordEntity.getReserveCheck())
                    .setMemberName(memberEntity.getName())
                    .setPhone(memberEntity.getPhone())
                    .setClassCheck(reservationRecordEntity.getStatus())
                    .setCardName(reservationRecordEntity.getCardName())
                    .setReserveNumbers(reservationRecordEntity.getReserveNums())
                    .setTimesCost(reservationRecordEntity.getReserveNums() * courseServiceById.getTimesCost())
                    .setOperateTime(reservationRecordEntity.getLastModifyTime())
                    .setOperator(reservationRecordEntity.getOperator())
                    .setReserveNote(reservationRecordEntity.getNote())
                    .setReserveId(reservationRecordEntity.getId());
            scheduleDetailReservedVoList.add(scheduleDetailReservedVo);
        }
        return scheduleDetailReservedVoList;
    }

    @PostMapping("/classRecord.do")
    @ResponseBody
    public R classRecord(Long id) {
        List<ClassRecordVo> classRecordVoList = new ArrayList<>();
        ScheduleRecordEntity scheduleRecordServiceById = scheduleRecordService.getById(id);
        CourseEntity courseServiceById = courseService.getById(scheduleRecordServiceById.getCourseId());
        List<ClassRecordEntity> classRecordEntityList = classRecordService.list(new QueryWrapper<ClassRecordEntity>()
                .eq("schedule_id", id)
                .eq("reserve_check", 0));
        for (ClassRecordEntity classRecordEntity : classRecordEntityList) {
            ReservationRecordEntity reservationRecordEntity = reservationRecordService.getOne(new QueryWrapper<ReservationRecordEntity>()
                    .eq("member_id", classRecordEntity.getMemberId())
                    .eq("schedule_id", classRecordEntity.getScheduleId())
                    .eq("card_id", classRecordEntity.getBindCardId()));
            MemberEntity memberEntity = memberService.getById(reservationRecordEntity.getMemberId());
            ClassRecordVo classRecordVo = new ClassRecordVo();
            classRecordVo.setMemberId(reservationRecordEntity.getMemberId())
                    .setClassRecordId(classRecordEntity.getId())
                    .setCardId(classRecordEntity.getBindCardId())
                    .setCheckStatus(classRecordEntity.getCheckStatus())
                    .setMemberName(memberEntity.getName())
                    .setMemberPhone(memberEntity.getPhone())
                    .setMemberSex(memberEntity.getSex())
                    .setMemberBirthday(memberEntity.getBirthday())
                    .setTimesCost(courseServiceById.getTimesCost())
                    .setReserveNums(reservationRecordEntity.getReserveNums())
                    .setCardName(reservationRecordEntity.getCardName())
                    .setOperateTime(reservationRecordEntity.getLastModifyTime());
            classRecordVoList.add(classRecordVo);
        }

        return R.ok().put("data", classRecordVoList);

    }

    @PostMapping("/consumeEnsureAll.do")
    @ResponseBody
    public R consumeEnsureAll(@RequestParam("scheduleId") Long id, @RequestParam("operator") String name) {
        //判断课程是否结束
        boolean isEnsureAll = scheduleRecordService.isEnsureAll(id);
        if (isEnsureAll) {
            if (scheduleRecordService.isConsum(id, name)) {
                return R.ok();
            } else {
                return R.error("有会员卡次数或金额不够，请充值！");
            }
        } else {
            return R.error("当前课程没有结束，扣费失败！");
        }
    }

    @PostMapping("/queryAmountsPayable.do")
    @ResponseBody
    public R queryAmountPayable(@RequestParam("bindCardId") Long bindCardId, @RequestParam("classId") Long classId, @RequestParam("timesCost") Integer timesCost, @RequestParam("scheduleId") Long scheduleId) {
        ScheduleRecordEntity scheduleRecordEntity = scheduleRecordService.getById(scheduleId);
        CourseEntity courseEntity = courseService.getById(scheduleRecordEntity.getCourseId());
        if (courseEntity != null) {
            return R.ok().put("data", courseEntity.getMoney());
        } else {
            return R.error("找不到对应的课程！");
        }
    }

    @PostMapping("/consumeEnsure.do")
    @ResponseBody
    public R consumeEnsure(ConsumeFormVo consumeFormVo) {
        //判断课程是否结束
        boolean isEnsureAll = scheduleRecordService.isEnsureAll(consumeFormVo.getScheduleId());
        if (isEnsureAll) {
            boolean isConsum = memberCardService.consum(consumeFormVo);
            if (isConsum) {
                return R.ok();
            } else {
                return R.error("您的会员卡次数或金额不够，请充值！");
            }
        } else {
            return R.error("当前课程没有结束，扣费失败！");

        }
    }

    @PostMapping("/deleteOne.do")
    @ResponseBody
    @CacheEvict(value = "courseCache", key = "1")
    public R deleteOne(Integer id) {
        boolean isDelete = scheduleRecordService.isDelete(id);
        if (isDelete) {
            return R.ok();
        } else {
            return R.error();
        }
    }

}
